#io多路复用


import selectors
import socket

sel = selectors.DefaultSelector()   #DefaultSelector会根据当前操作系统类型自己选择selector类型

def accept(sock, mask):
    coon, addr = sock.accept()
    print('accepted', coon, 'from', addr)
    coon.setblocking(False)
    sel.register(coon, selectors.EVENT_READ, read)  #对描述符进行注册，也就是对该描述符的EVENT_READ事件进行监听，当又READ事件通知时，调用回调函数read

def read(conn, mask):
    data = conn.recv(1024)
    if data:
        print('echoing', repr(data), 'to', conn)
        conn.send(data)
    else:
        print('closing', conn)
        sel.unregister(conn)       #　注销描述符
        conn.close

sock = socket.socket()
sock.bind(('localhost', 9999))
sock.listen(100)
sock.setblocking(False)     #设置socket的阻塞或非阻塞模式
sel.register(sock, selectors.EVENT_READ, accept)

while True:
    events = sel.select()   #默认是阻塞，有活动链接就返回活动的链接列表||　该函数是实现I/O异步的关键，等待，直到一些已注册的文件对象准备就绪，或者超时。　该函数返回一个元组(key, events)
    for key, mask in events:
        callback = key.data
        callback(key.fileobj, mask)